package com.asa.fushu.matrix;

import java.util.ArrayList;
import java.util.List;

import com.asa.fushu.bean.Fushu;
import com.asa.hutils.MathHUtils;

/**
 * 矩阵的运算，复数域上的
 * @author Administrator
 *
 */
public class MathHUtils_FUSHU {

	
	
	
	
	/**
	 * 矩阵的加法
	 * 
	 * @param a
	 * @param b
	 * @return
	 */
	public static Fushu[][] jiafa(Fushu[][] a, Fushu[][] b) {
		Fushu[][] asa = new Fushu[a.length][a[0].length];
		if (a.length != b.length || a[0].length != b[0].length) {
			throw new RuntimeException("哥们你这个矩阵长度都有问题呀，矩阵之间的行列数要相同才能相加");
		}
		for (int i = 0; i < asa.length; i++) {
			for (int j = 0; j < asa[i].length; j++) {
				asa[i][j] = a[i][j].add(b[i][j]);
			}
		}

		return asa;
	}
	
	
	/**
	 * 矩阵的转置
	 * 
	 * @param a
	 * @return
	 */
	public static Fushu[][] zhuanzhi(Fushu[][] a) {
		Fushu[][] asa = new Fushu[a[0].length][a.length];

		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < a[i].length; j++) {
				asa[j][i] = a[i][j];
			}
		}

		return asa;
	}
	
	
	
	/**
	 * 单位矩阵
	 * @param length
	 * @return
	 */
	public static Fushu[][] getI(int length) {
		// TODO Auto-generated method stub
		Fushu[][] I = new Fushu[length][length];
		
		for (int j = 0; j < I.length; j++) {
			I[j][j] = new Fushu(1, 0);
		}
		return I;
	}

	/**
	 * 乘法
	 * @param suanzi
	 * @param d
	 * @return
	 */
	public static Fushu[][] chenfa(Fushu[][] suanzi, Fushu d) {
		// TODO Auto-generated method stub
		
		Fushu[][] I = new Fushu[suanzi.length][suanzi[0].length];

		for (int j = 0; j < I.length; j++) {
			for (int k = 0; k < I[j].length; k++) {
				I[j][k] = suanzi[j][k].mul(suanzi[j][k], d);
			}
		}
		
		return I;
	}
	
	
	/**
	 * 矩阵的乘法
	 * 
	 * @param a
	 * @return
	 * @throws Exception
	 */
	public static Fushu[][] chenfa(Fushu[][] a, Fushu[][] b) {

		if (a[0].length != b.length) {
			throw new RuntimeException("哥们你这个矩阵长度都有问题呀，是不是没有转置");
		}
		Fushu[][] asa = new Fushu[a.length][b[0].length];
		for (int i = 0; i < asa.length; i++) {
			for (int j = 0; j < asa[i].length; j++) {
				asa[i][j] = new Fushu(0, 0);
			}
		}
		
		
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < b[0].length; j++) {
				for (int k = 0; k < a[0].length; k++) {
					asa[i][j].add(a[i][k].mul(a[i][k], b[k][j]));
				}
			}
		}

		return asa;
	}
	
	
	/**
	 * 厄米特（Hermitian）矩阵,共轭转置
	 * @return
	 */
	public static Fushu[][] Hermitian(Fushu[][] a){
		
		
		Fushu[][] asa = new Fushu[a.length][a[0].length];
		
		for (int i = 0; i < asa.length; i++) {
			for (int j = 0; j < asa[i].length; j++) {
				asa[i][j] = a[i][j].conjugate(a[i][j]);
			}
		}
		
		Fushu[][] zhuanzhi = zhuanzhi(asa);
		
		return zhuanzhi;
	}
	
	
	
	
	
	/**
	 * 矩阵范数
	 * lp范数 
	 * l1范数就是直接设置p=1
	 * p=2时叫Frobenius范数
	 */
	public Fushu l1(Fushu[][] asa,int p) {
		
		Fushu result = new Fushu();
		double count = 0;
		for (int i = 0; i < asa.length; i++) {
			for (int j = 0; j < asa[i].length; j++) {
				Fushu fushu = asa[i][j];
				double length = fushu.length();
				Math.pow(length, p);
				count+=length;
				
			}
			
		}
		
		result.real = Math.pow(count, 1.0/p);
		
		return result;
	}
	
	
	/**
	 * 谱范数
	 * @param asa
	 * @param p
	 * @return
	 */
	public double lspec(Fushu[][] asa,int p) {
		
		Fushu result = new Fushu();
		
		Fushu[][] hermitian = Hermitian(asa);
		
		Fushu[][] chenfa = chenfa(hermitian, asa);
		
		double[][] transform = transform(chenfa);
		
		double[] juzhengtezhengzhi = MathHUtils.juzhengtezhengzhi(transform);

		double max = juzhengtezhengzhi[0];
		
		for (int i = 0; i < juzhengtezhengzhi.length; i++) {
			if (juzhengtezhengzhi[i]>max) {
				max = juzhengtezhengzhi[i];
			}
		}
		
		
		
		
		return Math.pow(max, 0.5);
	}
	
	
	public static double[][] transform(Fushu[][] asa) {
		double[][] result = new double[asa.length][asa[0].length];
		for (int i = 0; i < asa.length; i++) {
			for (int j = 0; j < asa[i].length; j++) {
				result[i][j] = asa[i][j].real;
			}
		}
		
		return result;
	}

	
	/**
	 * Hadamard积
	 * @param aa
	 * @param bb
	 * @return
	 */
	public static Fushu[][] hadamard(Fushu[][] aa,Fushu[][] bb) {
		Fushu[][] result = new Fushu[aa.length][aa[0].length];
		for (int i = 0; i < aa.length; i++) {
			for (int j = 0; j < aa[i].length; j++) {
				result[i][j] = aa[i][j].mul(bb[i][j]);
			}
		}
		
		return result;
	}
	
	/**
	 * Kronecker积
	 * @param aa
	 * @param bb
	 * @return
	 */
	public static Fushu[][] Kronecker(Fushu[][] aa,Fushu[][] bb) {
		List<List<Fushu[][]>> result = new ArrayList<List<Fushu[][]>>();
		for (int i = 0; i < aa.length; i++) {
			List<Fushu[][]> e = new ArrayList<Fushu[][]>(aa[i].length);
			result.add(e);
		}
		
		
		
		for (int i = 0; i < aa.length; i++) {
			for (int j = 0; j < aa[i].length; j++) {
				result.get(i).set(j, chenfa(bb, aa[i][j]));
			}
			
		}
		Fushu [][] resultend = new Fushu[aa.length*bb.length][aa[0].length*bb[0].length];
		
		for (int i = 0; i < result.size(); i++) {
			for (int j = 0; j < result.get(i).size(); j++) {
				Fushu[][] ds = result.get(i).get(j);
				for (int k = 0; k < ds.length; k++) {
					for (int l = 0; l < ds.length; l++) {
						
						resultend[i*k][j*l] = ds[i][j];
						
					}
				}
				
				
			}
			
		}

		
		return resultend;
	}
	
	
}
